package cn.glc.daily.life.web.service.user.impl;

import cn.glc.daily.life.infrastructure.po.UserTaskPo;
import cn.glc.daily.life.infrastructure.repository.mysql.MysqlRepositories;
import cn.glc.daily.life.infrastructure.repository.redis.RedisRepository;
import cn.glc.daily.life.model.dto.user.task.UserTaskAddDto;
import cn.glc.daily.life.model.dto.user.task.UserTaskQueryDto;
import cn.glc.daily.life.model.dto.user.task.UserTaskUpdateDto;
import cn.glc.daily.life.model.dto.user.task.UserTaskUpdateStatusDto;
import cn.glc.daily.life.model.vo.page.PageConvert;
import cn.glc.daily.life.model.vo.user.task.UserTaskDetailVo;
import cn.glc.daily.life.model.vo.user.task.UserTaskVo;
import cn.glc.daily.life.web.convert.UserTaskConvert;
import cn.glc.daily.life.web.service.user.UserTaskService;
import cn.glc.daily.life.web.support.TaskSupport;
import cn.glc.daily.life.web.support.TransactionalSupport;
import cn.simon.free.redis.mq.core.producer.RedisMessageProducer;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import org.redisson.api.RMap;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;
import org.redisson.client.protocol.ScoredEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户任务
 *
 * @author simon
 * @date 2021/5/12 11:29
 * @copyright:
 * @modifier
 * @motto a no talent, people who have to study hard
 */
@Service
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class UserTaskServiceImpl implements UserTaskService {

    private final TaskSupport taskSupport;
    private final RedissonClient redissonClient;
    private final RedisMessageProducer redisMessageProducer;

    @Override
    public IPage<UserTaskVo> listPage(UserTaskQueryDto userTaskQueryDto) {
        return MysqlRepositories.userTaskRepository.listPage(PageConvert.convert2PageQuery(userTaskQueryDto), userTaskQueryDto)
                .convert(UserTaskConvert.INSTANCE::userTaskPo2IUserTaskVo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean addTask(UserTaskAddDto userTaskAddDto) {
        UserTaskPo userTaskPo = UserTaskConvert.INSTANCE.userTaskAddDto2Po(userTaskAddDto);
        TransactionalSupport.afterCompletion(() -> {
            redisMessageProducer.send("user_task_delay_queue", userTaskAddDto, 5, TimeUnit.SECONDS);
        });
        return MysqlRepositories.userTaskRepository.save(userTaskPo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteTask(Long uid) {
        TransactionalSupport.afterCompletion(() -> RedisRepository.redisUserTaskRepository.update(UserTaskConvert.INSTANCE.userTaskPo2Ro(MysqlRepositories.userTaskRepository.getById(uid))));
        return MysqlRepositories.userTaskRepository.removeById(uid);
    }

    @Override
    public UserTaskDetailVo queryTask(Long id) {
        RScoredSortedSet<Object> scoredSortedSet = redissonClient.getScoredSortedSet(String.valueOf(id));
        scoredSortedSet.add(10d, "zhangsan");
        Collection<ScoredEntry<Object>> scoredEntries = scoredSortedSet.entryRange(0, -1);
        scoredSortedSet.addAll(scoredEntries.stream().collect(Collectors.toMap(ScoredEntry::getValue, ScoredEntry::getScore)));
        RMap<Object, Object> map = redissonClient.getMap("123");
        map.put("1dsada", "dadjhakdka");
        UserTaskPo userTaskPo = MysqlRepositories.userTaskRepository.getById(id);
        return UserTaskConvert.INSTANCE.po2UserTaskDetail(userTaskPo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateTask(UserTaskUpdateDto userTaskUpdateDto) {
        UserTaskPo userTaskPo = UserTaskConvert.INSTANCE.userTaskUpdateDto2Po(userTaskUpdateDto);
        TransactionalSupport.afterCompletion(() -> RedisRepository.redisUserTaskRepository.update(UserTaskConvert.INSTANCE.userTaskPo2Ro(MysqlRepositories.userTaskRepository.getById(userTaskUpdateDto.getId()))));
        return MysqlRepositories.userTaskRepository.updateById(userTaskPo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateTaskStatus(UserTaskUpdateStatusDto userTaskUpdateStatusDto) {
        UserTaskPo userTaskPo = UserTaskConvert.INSTANCE.userTaskUpdateStatusDto2Po(userTaskUpdateStatusDto);
        TransactionalSupport.afterCompletion(() -> RedisRepository.redisUserTaskRepository.update(UserTaskConvert.INSTANCE.userTaskPo2Ro(MysqlRepositories.userTaskRepository.getById(userTaskUpdateStatusDto.getId()))));
        return MysqlRepositories.userTaskRepository.updateById(userTaskPo);
    }
}
